
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const blogSchema = new Schema({
    title: String,
    author: String,
    body: String,
    comments: [{ body: String, date: Date }],
    date: { type: Date, default: Date.now },
    hidden: Boolean,
    meta: {
        votes: Number,
        favs: Number
    }
});

const Blog = mongoose.model('Blog', blogSchema);
// ready to go!

// define a schema
var animalSchema = new Schema({ name: String, type: String });

// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function (cb) {
    return this.model('Animal').find({ type: this.type }, cb);
};

// 实例方法（method）

var Animal = mongoose.model('Animal', animalSchema);
var dog = new Animal({ type: 'dog' });

dog.findSimilarTypes(function (err, dogs) {
    console.log(dogs); // woof
});

// 静态方法（static）

// assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function (name, cb) {
    return this.find({ name: new RegExp(name, 'i') }, cb);
};

var Animal = mongoose.model('Animal', animalSchema);
Animal.findByName('fido', function (err, animals) {
    console.log(animals);
});

// 查询助手（query helper）
animalSchema.query.byName = function (name) {
    return this.find({ name: new RegExp(name, 'i') });
};

var Animal = mongoose.model('Animal', animalSchema);
Animal.find().byName('fido').exec(function (err, animals) {
    console.log(animals);
});

// 索引（index）

var animalSchema = new Schema({
    name: String,
    type: String,
    tags: { type: [String], index: true } // field level
});

animalSchema.index({ name: 1, type: -1 }); // schema level

// mongoose.connect('mongodb://user:pass@localhost:port/database', { autoIndex: false });
// or
// mongoose.createConnection('mongodb://user:pass@localhost:port/database', { autoIndex: false });
// or
// animalSchema.set('autoIndex', false);
// or
// new Schema({..}, { autoIndex: false });


// Will cause an error because mongodb has an _id index by default that
// is not sparse
animalSchema.index({ _id: 1 }, { sparse: true });
var Animal = mongoose.model('Animal', animalSchema);

Animal.on('index', function (error) {
    // "_id index cannot be sparse"
    console.log(error.message);
});

// 虚拟值（Virtual）

// define a schema
var personSchema = new Schema({
    name: {
        first: String,
        last: String
    }
});

// compile our model
var Person = mongoose.model('Person', personSchema);

// create a document
var axl = new Person({
    name: { first: 'Axl', last: 'Rose' }
});

personSchema.virtual('fullName').get(function () {
    return this.name.first + ' ' + this.name.last;
});

console.log(axl.fullName); // Axl Rose

personSchema.virtual('fullName').
    get(function () { return this.name.first + ' ' + this.name.last; }).
    set(function (v) {
        this.name.first = v.substr(0, v.indexOf(' '));
        this.name.last = v.substr(v.indexOf(' ') + 1);
    });

axl.fullName = 'William Rose'; // Now `axl.name.first` is "William"

// 别名（Alias）

var personSchema = new Schema({
    n: {
        type: String,
        // Now accessing `name` will get you the value of `n`, and setting `n` will set the value of `name`
        alias: 'name'
    }
});

// Setting `name` will propagate to `n`
var person = new Person({ name: 'Val' });
console.log(person); // { n: 'Val' }
console.log(person.toObject({ virtuals: true })); // { n: 'Val', name: 'Val' }
console.log(person.name); // "Val"

person.name = 'Not Val';
console.log(person); // { n: 'Not Val' }


// option: autoIndex

// var schema = new Schema({..}, { autoIndex: false });
// var Clock = mongoose.model('Clock', schema);
// Clock.ensureIndexes(callback);

// option: bufferCommands

mongoose.set('bufferCommands', true);
// Schema option below overrides the above, if the schema option is set.
// var schema = new Schema({..}, { bufferCommands: false });

// option: id


// default behavior
var schema = new Schema({ name: String });
var Page = mongoose.model('Page', schema);
var p = new Page({ name: 'mongodb.org' });
console.log(p.id); // '50341373e894ad16347efe01'

// disabled id
var schema = new Schema({ name: String }, { id: false });
var Page = mongoose.model('Page', schema);
var p = new Page({ name: 'mongodb.org' });
console.log(p.id); // undefined


// option: _id


// default behavior
var schema = new Schema({ name: String });
var Page = mongoose.model('Page', schema);
var p = new Page({ name: 'mongodb.org' });
console.log(p); // { _id: '50341373e894ad16347efe01', name: 'mongodb.org' }

// disabled _id
var childSchema = new Schema({ name: String }, { _id: false });
var parentSchema = new Schema({ children: [childSchema] });

var Model = mongoose.model('Model', parentSchema);

Model.create({ children: [{ name: 'Luke' }] }, function (error, doc) {
    // doc.children[0]._id will be undefined
});


// option: minimize

var schema = new Schema({ name: String, inventory: {} });
var Character = mongoose.model('Character', schema);

// will store `inventory` field if it is not empty
var frodo = new Character({ name: 'Frodo', inventory: { ringOfPower: 1 } });
Character.findOne({ name: 'Frodo' }, function (err, character) {
    console.log(character); // { name: 'Frodo', inventory: { ringOfPower: 1 }}
});

// will not store `inventory` field if it is empty
var sam = new Character({ name: 'Sam', inventory: {} });
Character.findOne({ name: 'Sam' }, function (err, character) {
    console.log(character); // { name: 'Sam' }
});


var schema = new Schema({ name: String, inventory: {} }, { minimize: false });
var Character = mongoose.model('Character', schema);

// will store `inventory` if empty
var sam = new Character({ name: 'Sam', inventory: {} });
Character.findOne({ name: 'Sam' }, function (err, character) {
    console.log(character); // { name: 'Sam', inventory: {}}
});





















